home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Risc World 3
/
Risc World 3.iso
/
SOFTWARE
/
ISSUE2
/
PD
/
VINCE
/
!ViNCe
/
c
/
vncviewer
< prev
Wrap
Text File
|
2002-07-10
|
32KB
|
1,103 lines
/*
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
/*
* vncviewer.c
*/
#include <stdio.h>
#include <time.h>
#include <string.h>
#include "oslib/os.h"
#include "oslib/osbyte.h"
#include "oslib/wimp.h"
#include "oslib/osspriteop.h"
#include "oslib/colourtrans.h"
#include "vncviewer.h"
#include "vnckeys.h"
#include "display.h"
#include "antitwit.h"
#define CFGFILE_LEN 1023
#define SH (1<<16)
DISPLAY display;
// choices
int savewhenquit = 0;
int fullscreen = 0;
int bgcolour = 0;
int offsetx = 0, offsety = 0;
int antitwit = 0;
int keepontop = 0;
int openontop = 0;
int noborder = 0;
char password[9];
int guess = 0;
int debug = 0;
int supporttight = 0;
int bpp = 16;
int displaycursor = 0;
int checkclientbitmap = 0;
int dither8 = 0;
int scale = 100;
int addrectshift = 1;
int fastcopy = 0;
#define CLOSEACTION_QUIT 0
#define CLOSEACTION_ICONBAR 1
#define CLOSEACTION_TOGGLESCALE 2
int closeaction = CLOSEACTION_QUIT;
// iconbar
wimp_i iconbarhandle;
osspriteop_area *iconbarsprite = NULL;
unsigned short rgb332_rgb555_table[256];
static wimp_w window;
static int connected = 0;
static int CreateSprite(void);
static int CreateWindow(void);
static void SendMouse(int force);
static void RedrawWindow(wimp_draw *draw, bool *more);
static unsigned short pressedkeys[32];
static int pressedkeyscount = 0;
static int releasekeystime = 0x7f000000;
static void release_keys(void);
static void send_keys(int key1, int key2);
static void send_key(int key);
static void close_window(void);
static void set_window_extent(void);
static int lastmousex, lastmousey, lastmousetime, lastmousebuttons, mouseinside;
static int lastkey, lastkeytime;
static int screensizex, screensizey, visiblex, visibley;
static char transtable[256];
static int done = 0;
static unsigned int versmaj = 0, versmin;
// Called with release = 1 to release the special keys at the end
// (very useful if the connection is shared).
void check_ctrl_alt(int release) {
static int altpressed = 0;
static int ctrlpressed = 0;
static int checktime = 0;
int alt = 0, ctrl = 0;
if (!release) {
if (clock() < checktime)
return;
checktime = clock()+3;
xos_byte(osbyte_SCAN_KEYBOARD, 0x80 | 1, 0, &ctrl, NULL);
xos_byte(osbyte_SCAN_KEYBOARD, 0x80 | 2, 0, &alt, NULL);
ctrl = !!ctrl;
alt = !!alt;
}
if (alt != altpressed) {
if (alt)
SendKeyEvent(VNCKEY_ALT, 1);
else
SendKeyEvent(VNCKEY_ALT, 0);
altpressed = alt;
}
if (ctrl != ctrlpressed) {
if (ctrl)
SendKeyEvent(VNCKEY_CTRL, 1);
else
SendKeyEvent(VNCKEY_CTRL, 0);
ctrlpressed = ctrl;
}
}
osspriteop_area *create_scaled_down_version(int sizex, int sizey) {
// create a scaled down version of the current screen
osspriteop_area *area;
int step, x, y, r, g, b, i;
unsigned short *rd, *wr, *tmp;
area = malloc(2*(sizex+1)*sizey+256);
if (!area) return NULL;
area->size = 2*(sizex+1)*sizey+256;
area->sprite_count = 0;
area->first = area->used = 16;
if (xosspriteop_create_sprite(osspriteop_USER_AREA, area, "sprite",
0, sizex, sizey, (os_mode)0x281680b5)) {
free(area);
return NULL;
}
tmp = malloc(2*sizex*display.sizey);
if (!tmp) {
free(area);
return NULL;
}
// first scale down horizontally
step = (1024*sizex)/display.sizex;
rd = display.data;
for (y = display.sizey; y > 0; y--) {
wr = tmp + sizex*(display.sizey-y);
x = r = g = b = 0;
for (i = display.sizex; i > 0; i--) {
r += (*rd) & 31;
g += ((*rd)>>5) & 31;
b += ((*rd)>>10) & 31;
rd++;
x += step;
if (x >= 1024) {
r = (r*step)/x;
g = (g*step)/x;
b = (b*step)/x;
if (r > 31) r = 31;
if (g > 31) g = 31;
if (b > 31) b = 31;
*wr++ = r | (g<<5) | (b<<10);
x -= 1024;
r = g = b = 0;
}
}
}
// then scale down vertically
step = (1024*sizey)/display.sizey;
for (x = sizex; x > 0; x--) {
rd = tmp + (sizex-x);
wr = (unsigned short *)(((char *)area) + 60);
wr += sizex-x;
y = r = g = b = 0;
for (i = display.sizey; i > 0; i--) {
r += (*rd) & 31;
g += ((*rd)>>5) & 31;
b += ((*rd)>>10) & 31;
rd += sizex;
y += step;
if (y >= 1024) {
r = (r*step)/y;
g = (g*step)/y;
b = (b*step)/y;
if (r > 31) r = 31;
if (g > 31) g = 31;
if (b > 31) b = 31;
*wr = r | (g<<5) | (b<<10);
wr += sizex;
y -= 1024;
r = g = b = 0;
}
}
}
free(tmp);
return area;
}
void poll() {
wimp_block wimp;
wimp_event_no action;
/* Some events are queued to avoid reentrancy problems. -- VL */
xwimp_poll(wimp_QUEUE_MOUSE|wimp_QUEUE_KEY, &wimp, NULL, &action);
switch (action) {
case wimp_OPEN_WINDOW_REQUEST:
xwimp_open_window(&wimp.open);
break;
case wimp_CLOSE_WINDOW_REQUEST:
close_window();
break;
case wimp_POINTER_ENTERING_WINDOW:
mouseinside = 1;
if (!displaycursor) xosbyte(osbyte_SELECT_POINTER, 0, 0);
xwimp_set_caret_position(window, -1, -1000, -1000, 40, -1);
break;
case wimp_POINTER_LEAVING_WINDOW:
mouseinside = 0;
if (!displaycursor) xosbyte(osbyte_SELECT_POINTER, 1, 0);
break;
case wimp_REDRAW_WINDOW_REQUEST:
{
bool more;
xwimp_redraw_window(&wimp.redraw, &more);
RedrawWindow(&wimp.redraw, &more);
}
break;
case wimp_USER_MESSAGE:
case wimp_USER_MESSAGE_RECORDED:
case wimp_USER_MESSAGE_ACKNOWLEDGE:
switch (wimp.message.action) {
case message_QUIT:
done = 1;
break;
}
}
}
int main(int argc, char **argv) {
unsigned int ip = 0;
int arg, displayn, i;
int wimpmsg[4];
char configfile[CFGFILE_LEN+1];
{ // Get ViNCe version
FILE *f;
f = fopen("<ViNCe$Dir>.Version", "r");
if (f != NULL) {
fscanf(f, "VERSION=%u.%u", &versmaj, &versmin);
fclose(f);
}
}
// parse arguments
displayn = 1; // default display
strcpy(password, "mypass");
*configfile = '\0';
for (arg = 1; arg < argc; arg++) {
if (strcmp(argv[arg], "-display") == 0) {
arg++;
displayn = atoi(argv[arg]);
} else if (strcmp(argv[arg], "-config") == 0) {
arg++;
strncpy(configfile, argv[arg], CFGFILE_LEN+1);
if (configfile[CFGFILE_LEN] != '\0') {
fprintf(stderr, "Config file name too long\n");
exit(1);
}
} else if (strcmp(argv[arg], "-password") == 0) {
arg++;
strncpy(password, argv[arg], 8);
password[8] = '\0';
} else if (strcmp(argv[arg], "-8bpp") == 0) {
bpp = 8;
} else if (strcmp(argv[arg], "-dither8") == 0) {
dither8 = 1;
} else if (strcmp(argv[arg], "-tight") == 0) {
supporttight = 1;
} else if (strcmp(argv[arg], "-save") == 0) {
savewhenquit = 1;
} else if (strcmp(argv[arg], "-checkclientbitmap") == 0) {
checkclientbitmap = 1;
} else if (strcmp(argv[arg], "-cursor") == 0) {
displaycursor = 1;
} else if (strcmp(argv[arg], "-debug") == 0) {
debug = 1;
} else if (strcmp(argv[arg], "-full") == 0) {
fullscreen = 1;
arg++;
if (sscanf(argv[arg], "%x", &bgcolour) != 1)
bgcolour = 0x00000000;
else
bgcolour <<= 8;
} else if (strcmp(argv[arg], "-guess") == 0) {
guess = 3;
} else if (strcmp(argv[arg], "-bottom") == 0) {
openontop = 0;
} else if (strcmp(argv[arg], "-top") == 0) {
openontop = 1;
} else if (strcmp(argv[arg], "-noborder") == 0) {
noborder = 1;
} else if (strcmp(argv[arg], "-ontop") == 0) {
keepontop = 1;
} else if (strcmp(argv[arg], "-anti") == 0) {
antitwit = 1;
} else if (strcmp(argv[arg], "-fastcopy") == 0) {
fastcopy = 1;
} else if (strcmp(argv[arg], "-scale") == 0) {
arg++;
scale = atoi(argv[arg]);
} else if (strcmp(argv[arg], "-closewindow") == 0) {
arg++;
closeaction = atoi(argv[arg]);
} else if (arg == argc-1) {
// the last argument must be ipaddress
unsigned int ip0, ip1, ip2, ip3;
if (sscanf(argv[argc-1], "%u.%u.%u.%u", &ip0, &ip1, &ip2, &ip3) == 4)
ip = (ip0<<0) | (ip1<<8) | (ip2<<16) | (ip3<<24);
else {
fprintf(stderr, "The last argument must be the IP address\n");
exit(1);
}
}
}
if (*configfile) {
FILE *fh;
fh = fopen(configfile, "r");
if (fh) {
while (!feof(fh)) {
char temp[512], arg[256], val[256];
fgets(temp, 255, fh);
temp[255] = '\0';
if (strchr(temp, '=')) {
char *t;
t = strchr(temp, '=');
*t++ = '\0';
sscanf(temp, "%s", arg);
sscanf(t, "%s", val);
} else
*arg = '\0';
if (strcmp(arg, "display") == 0) {
displayn = atoi(val);
} else if (strcmp(arg, "password") == 0) {
strncpy(password, val, 8);
password[8] = '\0';
} else if (strcmp(arg, "8bpp") == 0) {
if (atoi(val) == 1) bpp = 8;
} else if (strcmp(arg, "dither8") == 0) {
dither8 = !!atoi(val);
} else if (strcmp(arg, "tight") == 0) {
supporttight = !!atoi(val);
} else if (strcmp(arg, "save") == 0) {
savewhenquit = !!atoi(val);
} else if (strcmp(arg, "checkclientbitmap") == 0) {
checkclientbitmap = !!atoi(val);
} else if (strcmp(arg, "cursor") == 0) {
displaycursor = !!atoi(val);
} else if (strcmp(arg, "save") == 0) {
savewhenquit = !!atoi(val);
} else if (strcmp(arg, "full") == 0) {
fullscreen = 1;
if (sscanf(val, "%x", &bgcolour) != 1)
bgcolour = 0x00000000;
else
bgcolour <<= 8;
} else if (strcmp(arg, "guess") == 0) {
guess = atoi(val);
} else if (strcmp(arg, "noborder") == 0) {
noborder = !!atoi(val);
} else if (strcmp(arg, "ontop") == 0) {
keepontop = !!atoi(val);
} else if (strcmp(arg, "openontop") == 0) {
openontop = !!atoi(val);
} else if (strcmp(arg, "anti") == 0) {
antitwit = !!atoi(val);
} else if (strcmp(arg, "fastcopy") == 0) {
fastcopy = !!atoi(val);
} else if (strcmp(arg, "scale") == 0) {
scale = atoi(val);
} else if (strcmp(arg, "addrectshift") == 0) {
addrectshift = atoi(val);
} else if (strcmp(arg, "closewindow") == 0) {
closeaction = atoi(val);
} else if (strcmp(arg, "server") == 0) {
unsigned int ip0, ip1, ip2, ip3;
if (sscanf(val, "%u.%u.%u.%u", &ip0, &ip1, &ip2, &ip3) == 4)
ip = (ip0<<0) | (ip1<<8) | (ip2<<16) | (ip3<<24);
}
} // endwhile
fclose(fh);
} // endif
}
if (ip == 0) {
fprintf(stderr, "The IP address isn't defined\n");
exit(1);
}
// reset our display structure
display.displaycontext = NULL;
// dependencies
if (scale < 25) scale = 25;
if (scale > 200) scale = 200;
if (bpp == 8) supporttight = 0;
if (bpp != 16) dither8 = 0;
if (closeaction != CLOSEACTION_ICONBAR)
closeaction = CLOSEACTION_QUIT;
// setup as a Wimp task
// select which messages to receive
wimpmsg[0] = message_MODE_CHANGE;
wimpmsg[1] = 0;
// initialise the wimp
if (xwimp_initialise(310, "ViNCe", (wimp_message_list *) wimpmsg,
NULL, NULL))
exit(1);
// RGB332 table - used when either -8bpp or -dither8 is set
for (i = 0; i < 256; i++) {
int r, g, b;
r = i & 7;
g = (i>>3) & 7;
b = (i>>6) & 7;
r = (r*1168)/256;
g = (g*1168)/256;
b = (b*2728)/256;
rgb332_rgb555_table[i] = r | (g<<5) | (b<<10);
}
// Now enter the main loop, processing VNC messages.
done = 0;
lastmousex = lastmousey = lastmousetime = -1000;
mouseinside = 0;
lastkey = 0;
lastkeytime = 0;
while (!done) {
wimp_block wimp;
wimp_event_no action;
((int *) &wimp.key)[7] = 1<<15; // Set bit 15 to detect DeepKeys' presence
xwimp_poll(0, &wimp, NULL, &action);
switch (action) {
case wimp_NULL_REASON_CODE:
if (connected) {
int clk;
check_ctrl_alt(0);
clk = clock();
if (keepontop && (clk > keepontop)) {
wimp_window_state state;
state.w = window;
xwimp_get_window_state(&state);
state.next = wimp_TOP;
xwimp_open_window((wimp_open *)&state);
keepontop = clock() + 50;
if (displaycursor)
xosbyte(osbyte_SELECT_POINTER, 1, 0);
else
xosbyte(osbyte_SELECT_POINTER, 0, 0);
xwimp_set_caret_position(window, -1, -1000, -1000, 40, -1);
}
if (clk > releasekeystime) release_keys();
if ((clk > lastmousetime) && (mouseinside)) SendMouse(0);
if (!HandleRFBServerMessage()) {
fprintf(stderr, "Failed to read server msg\n");
done = 3;
}
{
static int flushtime = 0;
if (clock() > flushtime) {
display_flush();
flushtime = clock() + 3;
}
}
} else {
// make a TCP connection to the VNC server
Bool ok;
int attempts = guess;
int port = 5900 + displayn;
do {
ok = ConnectToRFBServer(ip, port);
if (ok)
break;
port++;
} while (attempts-- > 0);
if (!ok) {
done = 4;
} else {
// Initialise the VNC connection, including reading the password
if (!InitialiseRFBConnection()) {
done = 5;
} else {
// Tell the VNC server which pixel format and encodings we want to use
SetFormatAndEncodings();
// create sprite with the correct size
display.sizex = si.framebufferWidth;
display.sizey = si.framebufferHeight;
CreateSprite();
CreateWindow();
connected = 1;
SendFramebufferUpdateRequest(0,0,display.sizex,display.sizey,0);
}
}
}
break;
case wimp_CLOSE_WINDOW_REQUEST:
close_window();
break;
case wimp_POINTER_ENTERING_WINDOW:
mouseinside = 1;
SendMouse(1);
if (!displaycursor) xosbyte(osbyte_SELECT_POINTER, 0, 0);
xwimp_set_caret_position(window, -1, -1000, -1000, 40, -1);
break;
case wimp_POINTER_LEAVING_WINDOW:
mouseinside = 0;
if (!displaycursor) xosbyte(osbyte_SELECT_POINTER, 1, 0);
break;
case wimp_KEY_PRESSED:
if (mouseinside) {
wimp_key_no key;
release_keys();
key = wimp.key.c;
if (key >= 384) {
if (key < 512) {
static int keymap[] = {
0, VNCKEY_F1, VNCKEY_F2, VNCKEY_F3,
VNCKEY_F4, VNCKEY_F5, VNCKEY_F6, VNCKEY_F7,
VNCKEY_F8, VNCKEY_F9, VNCKEY_TAB, VNCKEY_END,
VNCKEY_LEFT, VNCKEY_RIGHT, VNCKEY_DOWN, VNCKEY_UP,
0, VNCKEY_F1|SH, VNCKEY_F2|SH, VNCKEY_F3|SH,
VNCKEY_F4|SH, VNCKEY_F5|SH, VNCKEY_F6|SH, VNCKEY_F7|SH,
VNCKEY_F8|SH, VNCKEY_F9|SH, VNCKEY_TAB|SH, VNCKEY_END|SH,
VNCKEY_LEFT|SH,VNCKEY_RIGHT|SH,VNCKEY_PAGEDOWN,VNCKEY_PAGEUP,
0, VNCKEY_F1, VNCKEY_F2, VNCKEY_F3,
VNCKEY_F4, VNCKEY_F5, VNCKEY_F6, VNCKEY_F7,
VNCKEY_F8, VNCKEY_F9, VNCKEY_TAB, VNCKEY_END,
VNCKEY_LEFT, VNCKEY_RIGHT, VNCKEY_DOWN, VNCKEY_UP,
0, VNCKEY_F1|SH, VNCKEY_F2|SH, VNCKEY_F3|SH,
VNCKEY_F4|SH, VNCKEY_F5|SH, VNCKEY_F6|SH, VNCKEY_F7|SH,
VNCKEY_F8|SH, VNCKEY_F9|SH, VNCKEY_TAB|SH, VNCKEY_END|SH,
VNCKEY_LEFT|SH,VNCKEY_RIGHT|SH,VNCKEY_PAGEDOWN,VNCKEY_PAGEUP,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
VNCKEY_F10, VNCKEY_F11, VNCKEY_F12, VNCKEY_INSERT,
0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
VNCKEY_F10|SH, VNCKEY_F11|SH, VNCKEY_F12|SH, VNCKEY_INSERT|SH,
0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
VNCKEY_F10, VNCKEY_F11, VNCKEY_F12, VNCKEY_INSERT,
0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
VNCKEY_F10|SH, VNCKEY_F11|SH, VNCKEY_F12|SH, VNCKEY_INSERT|SH,
0, 0
};
int vnckey;
vnckey = keymap[key-384];
if (vnckey) {
int extra;
extra = ((int *) &wimp.key)[7]; // written by DeepKeys module
switch ((extra & (1<<15)) == 0 && (key & ~0x31) == 0x18e ?
extra >> 16 : 0) {
case 33:
if (extra & 3)
send_keys(VNCKEY_SHIFT, VNCKEY_PAGEUP);
else
send_key(VNCKEY_PAGEUP);
break;
case 54:
if (extra & 3)
send_keys(VNCKEY_SHIFT, VNCKEY_PAGEDOWN);
else
send_key(VNCKEY_PAGEDOWN);
break;
case 89:
if (extra & 3)
send_keys(VNCKEY_SHIFT, VNCKEY_UP);
else
send_key(VNCKEY_UP);
break;
case 99:
if (extra & 3)
send_keys(VNCKEY_SHIFT, VNCKEY_DOWN);
else
send_key(VNCKEY_DOWN);
break;
default:
if (vnckey & SH)
send_keys(VNCKEY_SHIFT, vnckey & ~SH);
else
send_key(vnckey);
}
}
}
} else {
switch (key) {
case wimp_KEY_ESCAPE: { // Escape or Ctrl-[
int extra;
extra = ((int *) &wimp.key)[7]; // written by DeepKeys module
send_key((extra & (1<<15)) || (extra >> 16) == 0 ?
VNCKEY_ESCAPE : '['); // If DeepKeys not present, Escape sent.
break;
}
case wimp_KEY_DELETE: { // Delete or Ctrl-?
int extra;
extra = ((int *) &wimp.key)[7]; // written by DeepKeys module
send_key((extra & (1<<15)) || (extra >> 16) == 52 ?
VNCKEY_DELETE : '?'); // If DeepKeys not present, Delete sent.
break;
}
case wimp_KEY_HOME: { // Home or Ctrl-^
int extra;
extra = ((int *) &wimp.key)[7]; // written by DeepKeys module
send_key((extra & (1<<15)) || (extra >> 16) == 32 ?
VNCKEY_HOME : '^'); // If DeepKeys not present, Home sent.
break;
}
case 0: send_key('@');
break;
default:
if (key >= ' ')
send_key(key);
else if (key > 26)
send_key(key+64);
else if (key > 0) {
int shift;
xos_byte(osbyte_SCAN_KEYBOARD, 0x80 | 0, 0, &shift, NULL);
if (key == wimp_KEY_RETURN) { // Return or Enter or Ctrl-M
int extra;
extra = ((int *) &wimp.key)[7]; // written by DeepKeys module
if ((extra & (1<<15)) || (extra >> 16) != 84) {
// DeepKeys not present or it is not Ctrl-M
send_key(VNCKEY_ENTER);
break;
}
} // key == wimp_KEY_RETURN
else if (key == wimp_KEY_BACKSPACE) { // Backspace or Ctrl-H
int extra;
extra = ((int *) &wimp.key)[7]; // written by DeepKeys module
if ((extra & (1<<15)) || (extra >> 16) == 30) {
// DeepKeys not present or it is Backspace
send_key(VNCKEY_BACKSPACE);
break;
}
} // key == wimp_KEY_BACKSPACE
send_key(key + (shift ? 64 : 96));
} // key > 0
break;
}
}
}
break;
case wimp_MOUSE_CLICK:
if (wimp.pointer.w == wimp_ICON_BAR) {
wimp_window_state state;
state.w = window;
xwimp_get_window_state(&state);
state.next = wimp_TOP;
xwimp_open_window((wimp_open *)&state);
xwimp_delete_icon(wimp_ICON_BAR, iconbarhandle);
} else
SendMouse(1);
break;
case wimp_OPEN_WINDOW_REQUEST:
xwimp_open_window(&wimp.open);
break;
case wimp_REDRAW_WINDOW_REQUEST:
{
bool more;
xwimp_redraw_window(&wimp.redraw, &more);
RedrawWindow(&wimp.redraw, &more);
}
break;
case wimp_USER_MESSAGE:
case wimp_USER_MESSAGE_RECORDED:
case wimp_USER_MESSAGE_ACKNOWLEDGE:
switch (wimp.message.action) {
case message_QUIT:
done = 1;
break;
case message_MODE_CHANGE:
xcolourtrans_select_table_for_sprite(display.displaycontext,
(osspriteop_id)"sprite",
(os_mode)-1, (os_palette *)-1,
(osspriteop_trans_tab *)transtable, 0);
break;
}
}
}
if (connected)
check_ctrl_alt(1);
if (savewhenquit)
xosspriteop_save_sprite_file(osspriteop_USER_AREA,
(osspriteop_area *)display.displaycontext,
"<ViNCe$Dir>.screendump");
xosbyte(osbyte_SELECT_POINTER, 1, 0);
CloseConnection();
return 0;
}
int CreateSprite() {
osspriteop_area *area;
display.displaycontext = malloc(2*(display.sizex+1)*display.sizey+256);
if (!display.displaycontext) return 1;
area = display.displaycontext;
area->size = 2*(display.sizex+1)*display.sizey+256;
area->sprite_count = 0;
area->first = area->used = 16;
if (xosspriteop_create_sprite(osspriteop_USER_AREA, area, "sprite",
0, display.sizex, display.sizey, (os_mode)0x281680b5))
return 1;
display.shortsperline = (display.sizex+1) & ~1;
display.data = (unsigned short *)(((char *)area)+60);
xcolourtrans_select_table_for_sprite(display.displaycontext,
(osspriteop_id)"sprite",
(os_mode)-1, (os_palette *)-1,
(osspriteop_trans_tab *)transtable, 0);
return 0;
}
int CreateWindow() {
wimp_window win;
int sx, sy;
static char titletext[24];
xos_read_mode_variable((os_mode)-1, os_MODEVAR_XWIND_LIMIT, &sx, NULL);
xos_read_mode_variable((os_mode)-1, os_MODEVAR_YWIND_LIMIT, &sy, NULL);
screensizex = 2*(sx+1);
screensizey = 2*(sy+1);
visiblex = display.sizex*2*scale/100;
visibley = display.sizey*2*scale/100;
offsetx = (screensizex - visiblex)/2;
offsety = (screensizey - visibley)/2;
// create a window
if (fullscreen) {
win.visible.x0 = 0;
win.visible.y0 = 0;
win.visible.x1 = screensizex;
win.visible.y1 = screensizey;
} else {
win.visible.x0 = offsetx;
win.visible.y0 = offsety;
win.visible.x1 = win.visible.x0 + visiblex;
win.visible.y1 = win.visible.y0 + visibley;
}
win.next = wimp_BOTTOM;
if (noborder)
win.flags = wimp_WINDOW_MOVEABLE | wimp_WINDOW_NO_BOUNDS | wimp_WINDOW_NEW_FORMAT;
else
win.flags = wimp_WINDOW_VSCROLL | wimp_WINDOW_HSCROLL |
wimp_WINDOW_SIZE_ICON | wimp_WINDOW_TITLE_ICON |
wimp_WINDOW_BACK_ICON | wimp_WINDOW_TOGGLE_ICON |
wimp_WINDOW_MOVEABLE | wimp_WINDOW_NO_BOUNDS |
wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_NEW_FORMAT;
win.title_fg = 7;
win.title_bg = 2;
win.work_fg = 7;
win.work_bg = 0xff;
win.scroll_outer = 3;
win.scroll_inner = 1;
win.highlight_bg = 12;
if (fullscreen) {
win.extent.x0 = -offsetx;
win.extent.y0 = -offsety;
win.extent.x1 = visiblex + offsetx;
win.extent.y1 = visibley + offsety;
} else {
win.extent.x0 = 0;
win.extent.y0 = 0;
win.extent.x1 = visiblex;
win.extent.y1 = visibley;
}
win.title_flags = wimp_ICON_TEXT | wimp_ICON_HCENTRED |
wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED;
win.work_flags = wimp_BUTTON_CLICK<<12;
win.sprite_area = (osspriteop_area *)1;
win.xmin = win.ymin = 100;
if (versmaj > 0)
sprintf(titletext, "ViNCe (version %u.%u)", versmaj, versmin);
else
sprintf(titletext, "ViNCe");
win.title_data.indirected_text.text = titletext;
win.title_data.indirected_text.validation = NULL;
win.title_data.indirected_text.size = strlen(titletext);
win.icon_count = 0;
if (xwimp_create_window(&win, &window)) return 1;
set_window_extent();
return 0;
}
void set_window_extent() {
wimp_window_state state;
visiblex = display.sizex*2*scale/100;
visibley = display.sizey*2*scale/100;
offsetx = (screensizex - visiblex)/2;
offsety = (screensizey - visibley)/2;
// set extent
state.w = window;
xwimp_get_window_state(&state);
if (keepontop || openontop)
state.next = wimp_TOP;
else
state.next = wimp_BOTTOM;
xwimp_open_window((wimp_open *)&state);
}
void SendMouse(int force) {
wimp_pointer ptr;
wimp_window_state state;
int x, y, but;
state.w = window;
xwimp_get_window_state(&state);
lastmousetime = clock() + 1;
xwimp_get_pointer_info(&ptr);
x = 100*(ptr.pos.x - (state.visible.x0 - state.xscroll))/(2*scale);
y = display.sizey - 100*(ptr.pos.y - (state.visible.y1 - state.yscroll))/(2*scale);
but = 0;
if (ptr.buttons & 1) but |= 4;
if (ptr.buttons & 2) but |= 2;
if (ptr.buttons & 4) but |= 1;
if (force || x != lastmousex || y != lastmousey || lastmousebuttons != but) {
SendPointerEvent(x, y, but);
lastmousex = x;
lastmousey = y;
lastmousebuttons = but;
}
}
void UpdateWindow(int x, int y, int w, int h) {
int x1, y1;
wimp_draw draw;
bool more;
x1 = 2*(x+w);
y1 = 2*(display.sizey-y);
x = 2*x;
y = 2*(display.sizey-(y+h));
x = x*scale/100;
y = y*scale/100;
x1 = x1*scale/100;
y1 = y1*scale/100;
draw.w = window;
draw.box.x0 = x-2;
draw.box.y0 = y-2;
draw.box.x1 = x1+2;
draw.box.y1 = y1+2;
xwimp_update_window(&draw, &more);
RedrawWindow(&draw, &more);
}
void RedrawWindow(wimp_draw *draw, bool *more) {
int x, y;
os_factors scaling;
scaling.xmul = scaling.ymul = scale;
scaling.xdiv = scaling.ydiv = 100;
x = draw->box.x0 - draw->xscroll;
y = draw->box.y1 - draw->yscroll;
while (*more) {
int antix0, antiy0, antix1, antiy1;
antix0 = draw->clip.x0;
antiy0 = draw->clip.y0;
antix1 = draw->clip.x1;
antiy1 = draw->clip.y1;
xosspriteop_put_sprite_scaled(osspriteop_USER_AREA,
display.displaycontext,
(osspriteop_id)"sprite", x, y, 0, &scaling,
(osspriteop_trans_tab *)transtable);
if (fullscreen) {
xcolourtrans_set_gcol(bgcolour, 0, 0, NULL, NULL);
if (antix0 < x) {
xos_plot(os_MOVE_TO, 0, 0);
xos_plot(os_PLOT_TO | os_PLOT_RECTANGLE, offsetx, screensizey);
}
if (antiy0 < x) {
xos_plot(os_MOVE_TO, offsetx, 0);
xos_plot(os_PLOT_TO | os_PLOT_RECTANGLE, offsetx + visiblex, offsety);
}
if (antix1 > visiblex + x) {
xos_plot(os_MOVE_TO, offsetx + visiblex, 0);
xos_plot(os_PLOT_TO | os_PLOT_RECTANGLE, screensizex, screensizey);
}
if (antiy1 > visibley + y) {
xos_plot(os_MOVE_TO, offsetx, offsety + visibley);
xos_plot(os_PLOT_TO | os_PLOT_RECTANGLE, offsetx + visiblex, screensizey);
}
}
xwimp_get_rectangle(draw, more);
if (antitwit) antitwitter(antix0, antiy0, antix1-antix0, antiy1-antiy0);
}
}
void release_keys() {
int i;
for (i = 0; i < pressedkeyscount; i++) {
SendKeyEvent(pressedkeys[i], 0);
}
pressedkeyscount = 0;
releasekeystime = 0x7f000000; // never
}
void send_keys(int key1, int key2) {
if (pressedkeyscount >= 30) return;
pressedkeys[pressedkeyscount+0] = key2;
pressedkeys[pressedkeyscount+1] = key1;
pressedkeyscount += 2;
SendKeyEvent(key1, 1);
SendKeyEvent(key2, 1);
releasekeystime = clock()+4;
}
void send_key(int key) {
if (pressedkeyscount >= 32) return;
pressedkeys[pressedkeyscount] = key;
pressedkeyscount++;
SendKeyEvent(key, 1);
releasekeystime = clock()+4;
}
void close_window() {
switch (closeaction) {
case CLOSEACTION_QUIT:
done = 2;
break;
case CLOSEACTION_ICONBAR:
{
int x, y;
if (iconbarsprite) free(iconbarsprite);
y = 42;
x = (1+(y*display.sizex)/display.sizey) & ~1;
iconbarsprite = create_scaled_down_version(x, y);
if (iconbarsprite) {
wimp_icon_create icon;
icon.w = (wimp_w) -1;
icon.icon.extent.x0 = 0;
icon.icon.extent.y0 = -4;
icon.icon.extent.x1 = 2*x;
icon.icon.extent.y1 = icon.icon.extent.y0 + 2*y;
icon.icon.flags = 0x0000311a;
icon.icon.data.indirected_sprite.id = (osspriteop_id)"sprite";
icon.icon.data.indirected_sprite.area = (osspriteop_area *)iconbarsprite;
icon.icon.data.indirected_sprite.size = strlen("sprite")+1;
xwimp_create_icon(&icon, &iconbarhandle);
xwimp_close_window(window);
} else
done = 2;
}
break;
case CLOSEACTION_TOGGLESCALE:
{
static int firsttime = 1, toggled = 0, scale1, scale2;
if (firsttime) {
firsttime = 0;
scale1 = scale;
if (scale1 == 100)
scale2 = 25;
else
scale2 = 100;
}
if (toggled)
scale = scale1;
else
scale = scale2;
toggled = !toggled;
set_window_extent();
UpdateWindow(0, 0, display.sizex, display.sizey);
}
break;
}
}
int fast_copy_ok() {
if (fastcopy && scale == 100) {
wimp_window_state state;
wimp_window_flags mask = wimp_WINDOW_NOT_COVERED|wimp_WINDOW_FULL_SIZE;
state.w = window;
xwimp_get_window_state(&state);
return (state.flags & mask) == mask;
}
else
return 0;
}
void BlockCopy(int rx, int ry, int rw, int rh, int sx, int sy) {
int x0, y0, x1, y1, xd, yd;
display_flush();
x0 = 2*sx;
x1 = 2*(sx+rw);
y0 = 2*(display.sizey-(sy+rh));
y1 = 2*(display.sizey-sy);
xd = 2*rx;
yd = 2*(display.sizey-(ry+rh));
xwimp_block_copy(window, x0, y0, x1, y1, xd, yd);
}